<style lang="less">
    .function-tree {
        & {
            width: 100%;
            // padding-bottom: 200px;
            min-height: 300px;
            overflow: auto;
        }
        .divider {
            margin-left: 4px;
            margin-right: 4px;
        }
    }
</style>
<template>
    <div class="function-tree">
        <a-tree checkable :default-expand-all="false" :blockNode="false" :selected-keys="selectedKeys" :tree-data="treeData" :expandedKeys="expandedKeys" :draggable="false" :checkedKeys="vmCheckedKeys" :checkStrictly="true" @select="onTreeSelect" @expand="onExpand" @check="onCheck">
        </a-tree>
    </div>
</template>
<script>
    import { delCategoryTreeNode, updateCategoryTreeNodeSort } from '@/api/common';
    import { roleMenuTreeselect } from '@/api/menu';
    export default {
        props: {
            type: {
                type: Number,
                require: true
            },
            /** 是否有操作功能 */
            hasOper: {
                type: Boolean,
                default: () => false
            },
            title: {
                type: String,
                default: () => null
            },
            rootKey: {
                type: String,
                default: () => '0'
            },
            roleId:String
        },
        data() {
            return {
                // 选中的
                selectedKeys: [],
                // 状态树
                treeData: [],
                // 展开的树节点
                expandedKeys: [],
                // 勾选
                checkedKeys:[],
                vmCheckedKeys:{
                    checked:[],
                    halfChecked:[]
                }
            }
        },
        computed: {
            // checkedKeys:{
            //     get(){
            //         return this.vmCheckedKeys;
            //     },
            //     set(newVal,oldVal){
            //         if (newVal==oldVal)return;
            //         this.$emit('onChecked', newVal);
            //         console.log(newVal);
            //         this.vmCheckedKeys = newVal;
            //     }
            // }
        },
        created() {
            
        },
        methods: {
            async refresh() {
                this.expandedKeys = [];
                let data = await roleMenuTreeselect(this.roleId);
                console.log(data)
                this.vmCheckedKeys.checked = data.checkedKeys.map(i=>''+i);
                const ignoreArr = ["4","3","2","1"];
                const arr = data.menus.filter(i=>!ignoreArr.includes(i.id));
                const title = this.title||'';
                this.treeData = [
                    ...nodeDataToVMNodeData(arr)
                ];
                this.$emit('onChecked', this.vmCheckedKeys.checked);
            },
            onTreeSelect(selectedKeys, e) {
                this.setTreeSelected(selectedKeys);
                if (e.selected) {
                    this.$emit('selected', e.node.dataRef);
                } else {
                    this.$emit('selected', null);
                }
            },
            onExpand(expandedKeys) {
                this.expandedKeys = expandedKeys;
            },
            setTreeSelected(selectedKeys) {
                this.selectedKeys = [...selectedKeys];
                if (selectedKeys.length > 0 && selectedKeys[0] == 0) {
                    selectedKeys[0] = null;
                };
            },

            addNode(item) {
                this.$refs.edit.show({
                    parentId: item.key == this.rootKey ? '0' : item.key,
                    parentName: item.title,
                    type: this.type,
                    onOk: async () => {
                        await this.refresh();
                        this.expandedKeys.push(item.key);
                    }
                });
            },
            showNodeDetail(item) {
                this.$refs.detail.show({
                    id: item.key
                });
            },
            showNodeEdit(item) {
                this.$refs.edit.show({
                    id: item.key,
                    onOk: async () => {
                        await this.refresh();
                    }
                });
            },
            delNode(item) {
                if (item.children && item.children.length > 0) {
                    this.$warning({
                        title: '提示',
                        content: `当前分类包含下级分类，不可被删除！`
                    })
                    return;
                }
                this.$confirm({
                    title: '提示',
                    content: `确定要删除当前分类？`,
                    onOk: async () => {
                        await delCategoryTreeNode({ id: item.id });
                        await this.refresh();
                    }
                });
            },
            async upNode(item) {
                const res = queryNodeInTree(item.key, { children: this.treeData });
                if (!res) {
                    throw Error('未找到节点！', item);
                }
                const arr = res.pNode.children;
                const index = arr.findIndex(i => i.key == item.key);
                const node = arr[index];
                const preNode = arr[index - 1];
                    await updateCategoryTreeNodeSort({
                        maxId: node.key,
                        maxSortNo: node.sortNo,
                        minId: preNode.key,
                        minSortNo: preNode.sortNo
                    });
                // 对调两节点位置
                let { isFirst, isLast } = preNode;
                preNode.isFirst = node.isFirst;
                preNode.isLast = node.isLast;
                node.isFirst = isFirst;
                node.isLast = isLast;
                arr[index] = preNode;
                arr[index - 1] = node;
                this.expandedKeys = [...this.expandedKeys];
            },
            async downNode(item) {
                const res = queryNodeInTree(item.key, { children: this.treeData });
                if (!res) {
                    throw Error('未找到节点！', item);
                }
                const arr = res.pNode.children;
                const index = arr.findIndex(i => i.key == item.key);
                const node = arr[index];
                const nextNode = arr[index + 1];
             
                    await updateCategoryTreeNodeSort({
                        maxId: nextNode.key,
                        maxSortNo: nextNode.sortNo,
                        minId: node.key,
                        minSortNo: node.sortNo
                    });


                // 对调两节点位置
                let { isFirst, isLast } = nextNode;
                nextNode.isFirst = node.isFirst;
                nextNode.isLast = node.isLast;
                node.isFirst = isFirst;
                node.isLast = isLast;
                arr[index] = nextNode;
                arr[index + 1] = node;
                this.expandedKeys = [...this.expandedKeys];
            },
            onCheck(item, e){
                this.vmCheckedKeys=item;
                this.$emit('onChecked', this.vmCheckedKeys.checked);
            }
        }
    }
    /**
     * 节点数据转换为视图节点数据
     * @param {Array} nodeDatas
     */
    function nodeDataToVMNodeData(nodeDatas) {
        return nodeDatas.map((i, index) => {
            if (i.children) {
                i.children = nodeDataToVMNodeData(i.children);
            }

            let menuTypeStr = i.menuType;
            if (i.menuType=='M') {
                menuTypeStr = '目录';
            }else if (i.menuType=='C') {
                menuTypeStr = '菜单';
            }else if (i.menuType=='F') {
                menuTypeStr = '按钮';
            }
            Object.assign(i, {
                title: `${i.label}-${menuTypeStr}`,
                key: ''+i.id,
                // scopedSlots: { title: 'custom' },
                // isFirst: index == 0 ? true : false,
                // isLast: index == nodeDatas.length - 1 ? true : false
            });
            return i;
        })
    }

    /**
     * 树中查询节点
     * @returns {{
            node: item,
            pNode: tree
       }}
     */
    function queryNodeInTree(key, tree) {
        if (!tree.children) {
            return null;
        }
        if(tree.children.length==0){
            return null;
        }
        const item = tree.children.find(i => i.key == key);
        if (item) {
            return {
                node: item,
                pNode: tree
            };
        }
        const arr = tree.children.map(i => queryNodeInTree(key, i));
        return arr.find(i=>i!=null);
    }
</script>